﻿/*
 
这个文件包含了主窗体的构造函数、UI 控件事件处理、串口逻辑、日志记录以及 TCP 监听的回调方法。
 
*/


using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Configuration; // 引入 System.Configuration 命名空间 (需要添加项目引用)

namespace ShangWeiDemo1
{
    public partial class Main : Form
    {
        // 1. 串口对象：用于建立和管理物理连接
        private SerialPort _serialPort;
        // 2. 扫码数据缓存：用于处理串口数据碎片化
        private StringBuilder _serialBuffer = new StringBuilder();
        // 3. HttpClient实例，用于发送HTTP请求
        private HttpClient _httpClient;
        // 用于日志文件操作的线程同步锁对象
        private static readonly object _logFileLock = new object();

        // **新增：上次成功查询的零件号**
        private string _lastSpecs = null; // 用于存储上次成功的零件号



        // **注入拆分后的服务**
        private TcpClientManager _tcpClientManager;
        private TcpServerListener _tcpServerListener;
        private MesService _mesService;

        // **关键流程控制状态变量**
        private bool _isWaitingForResult = false;
        private string _currentProcessingBarcode = string.Empty;

        // **记录已完成检测的条码和最终结果 (实现“一件一结果”的记录)**
        private Dictionary<string, string> _finalResults = new Dictionary<string, string>();

        // **VisionMaster 结果监听端口**
        private const int ResultListenPort = 9528;


        public Main()
        {
            InitializeComponent();
            this.FormClosing += Main_FormClosing;

            // 初始化 HttpClient
            _httpClient = new HttpClient();
            _httpClient.Timeout = TimeSpan.FromSeconds(10);

            // **NEW: 初始化拆分后的服务**
            _tcpClientManager = new TcpClientManager(this.WriteToLogFile);

            // 关键修复: 传入 this (当前窗体实例) 作为最后一个参数，以修复之前的 CS0103/CS0173 错误
            _tcpServerListener = new TcpServerListener(
                 ResultListenPort,
                 this.WriteToLogFile,
                 ProcessFinalResult,
                 this // 传入当前窗体实例 (this)
            );

            _mesService = new MesService(this.WriteToLogFile, _httpClient);

            InitializeSerialConnection();
            _tcpServerListener.StartListening();
        }

        // 窗体关闭事件，用于停止所有后台任务和释放资源
        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            _tcpServerListener.StopListening();

            if (_serialPort != null && _serialPort.IsOpen)
            {
                _serialPort.Close();
                _serialPort.Dispose();
            }

            _tcpClientManager.CloseConnection();
        }

        // ==========================================================
        // VisionMaster 结果处理逻辑 (由 TcpServerListener 回调)
        // ==========================================================

        /// <summary>
        /// 处理最终的检测结果 (OK/NG)，更新 UI 状态灯 (在大正方形 Label 上)
        /// 此方法已由 BeginInvoke 保证在 UI 线程执行
        /// </summary>
        public void ProcessFinalResult(string barcode, string finalResult)
        {
            // 0. **关键检查：检查是否与当前正在处理的条码匹配**
            if (barcode != _currentProcessingBarcode || !_isWaitingForResult)
            {
                // 如果结果的条码与当前正在处理的条码不一致，或者流程状态已重置（表示当前件的结果已处理），则直接忽略。

                // 【已修改】根据用户要求，忽略的结果不再打印日志，直接返回。
                return;
            }

            // 1. **核心逻辑：记录/更新最终结果，允许重测覆盖结果**
            string logPrefix = _finalResults.ContainsKey(barcode) ? "【结果更新】" : "【结果记录】";

            // 覆盖或添加结果，以支持重测逻辑
            _finalResults[barcode] = finalResult;
            WriteToLogFile($"{logPrefix}启动码 [{barcode}] 最终结果记录/更新为 [{finalResult}]。");

            // 2. **流程状态重置**
            // 无论收到的是否是第一次结果，只要是当前正在处理的件，就重置流程状态
            _isWaitingForResult = false;
            _currentProcessingBarcode = string.Empty;
            WriteToLogFile($"【流程结束】当前件 [{barcode}] 检测结果已返回，流程状态重置。");

            // 3. 更新 UI
            Label statusControl = this.Controls.Find("statusTextLabel", true).FirstOrDefault() as Label;

            if (statusControl == null)
            {
                WriteToLogFile("警告: 状态显示控件 (statusTextLabel) 未找到，无法更新UI!");
                return;
            }

            // UI 始终显示当前返回的结果
            string resultToDisplay = finalResult;

            if (resultToDisplay == "OK")
            {
                statusControl.Text = "OK";
                statusControl.BackColor = System.Drawing.Color.LimeGreen;
                statusControl.ForeColor = System.Drawing.Color.White;
            }
            else if (resultToDisplay == "NG")
            {
                statusControl.Text = "NG";
                statusControl.BackColor = System.Drawing.Color.Red;
                statusControl.ForeColor = System.Drawing.Color.White;
            }
            else
            {
                statusControl.Text = "N/A";
                statusControl.BackColor = System.Drawing.Color.Yellow;
                statusControl.ForeColor = System.Drawing.Color.Black;
            }
        }

        // ==========================================================
        // 串口和扫码逻辑
        // ==========================================================

        private void 扫码枪串口ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //实例化 Form_Config 窗体
            //假设 Form_Config 类存在
            Form_Config configForm = new Form_Config();
            DialogResult result = configForm.ShowDialog();

            if (result == DialogResult.OK)
            {
                InitializeSerialConnection();
            }
        }


        private void InitializeSerialConnection()
        {
            // 1. 清理：如果旧的串口对象存在且处于打开状态，先关闭和销毁
            if (_serialPort != null && _serialPort.IsOpen)
            {
                _serialPort.Close();
                _serialPort.Dispose();
                _serialPort = null;
            }

            // 2. 从应用设置中获取配置的端口名
            string portName = Properties.Settings.Default.PortName;

            if (string.IsNullOrEmpty(portName)) return;

            try
            {
                // 3. 实例化并设置参数
                _serialPort = new SerialPort(portName);

                _serialPort.BaudRate = 9600;
                _serialPort.DataBits = 8;
                _serialPort.Parity = Parity.None;
                _serialPort.StopBits = StopBits.One;

                // 4. 绑定核心事件：数据接收事件
                _serialPort.DataReceived += SerialPort_DataReceived;

                // 5. 打开端口
                _serialPort.Open();

                WriteToLogFile($"串口连接成功: {portName}");
            }
            catch (Exception ex)
            {
                // 6. 连接失败处理
                if (_serialPort != null)
                {
                    _serialPort.Dispose();
                    _serialPort = null;
                }
                MessageBox.Show($"串口连接失败 ({portName}): {ex.Message}，请检查设备或配置。", "连接错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                WriteToLogFile($"串口连接失败: {ex.Message}");
            }
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (_serialPort == null || !_serialPort.IsOpen) return;

            try
            {
                string receivedData = _serialPort.ReadExisting();
                _serialBuffer.Append(receivedData);

                char[] terminators = { '\r', '\n' };
                int endOfCodeIndex = _serialBuffer.ToString().IndexOfAny(terminators);

                while (endOfCodeIndex > -1)
                {
                    string completeCode = _serialBuffer.ToString().Substring(0, endOfCodeIndex).Trim();
                    _serialBuffer.Remove(0, endOfCodeIndex + 1);

                    if (!string.IsNullOrEmpty(completeCode))
                    {
                        ProcessScannedDataSafe(completeCode);
                    }

                    endOfCodeIndex = _serialBuffer.ToString().IndexOfAny(terminators);
                }
            }
            catch (Exception)
            {
                // 记录异常，防止辅助线程崩溃
            }
        }


        /// <summary>
        /// 实现线程安全地处理和验证扫码数据
        /// </summary>
        private void ProcessScannedDataSafe(string barcode)
        {
            // 确保在 UI 线程执行
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new Action<string>(ProcessScannedDataSafe), barcode);
                return;
            }

            // --- 以下代码在 UI 主线程执行 ---

            // 1. **关键检查：检查是否有件正在处理 (流程阻塞判断)**
            if (_isWaitingForResult)
            {
                // **【核心修改】**：无论扫入的是新码还是旧码，只要前一个件的流程锁未解除，就一律阻塞。
                MessageBox.Show($"等待前件 [{_currentProcessingBarcode}] 检测结果返回中，请稍后再扫码！", "操作受限", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                WriteToLogFile($"【操作受限】新的扫码 [{barcode}]，但前件 [{_currentProcessingBarcode}] 结果尚未返回，阻止流程。");
                // 关键：阻止流程继续
                return;
            }
            // ---------------------------------------------------------------------------------------

            // 2. 正常启动流程
            _isWaitingForResult = true;
            _currentProcessingBarcode = barcode;

            this.startCode_textBox.Text = barcode;
            string scanResult = barcode;

            // 3. 扫码格式校验
            // 这里的正则 pattern 是硬编码的，如果需要配置化，请参考您之前的截图 image_de4614.png 中的注释
            string pattern = @"^[0-9]{2,3}\-[a-zA-Z]*MO[0-9]*\$\$[0-9]*";
            string logMsg = string.Empty;

            try
            {
                if (Regex.IsMatch(scanResult, pattern, RegexOptions.IgnoreCase))
                {
                    // 合法分支：匹配成功
                    this.startCode_textBox.BackColor = System.Drawing.Color.LightGreen;
                    this.startCode_textBox.Text = scanResult;
                    Application.DoEvents();

                    logMsg = "扫码输入启动码：匹配成功：" + scanResult;
                    WriteToLogFile("--------------------------------------------------");
                    WriteToLogFile(logMsg);

                    // 触发 MES 接口查询
                    TriggerMesQuery(scanResult);
                }
                else
                {
                    // 非法分支：未匹配成功
                    this.startCode_textBox.BackColor = System.Drawing.Color.Red;
                    this.startCode_textBox.Text = $"非法格式: {scanResult}";
                    Application.DoEvents();

                    logMsg = "扫码输入非法字符：未匹配：" + scanResult;
                    WriteToLogFile(logMsg);

                    // 格式非法时，直接发 NG 结果给 VisionMaster
                    Task.Run(() => _tcpClientManager.SendDataToTcpServer($"{scanResult},false"));
                    // 此时 VisionMaster 接收到结果后，仍会回调 ProcessFinalResult 来重置状态
                }
            }
            catch (Exception ex)
            {
                this.startCode_textBox.BackColor = System.Drawing.Color.Yellow;
                this.startCode_textBox.Text = $"内部错误: {ex.Message}";
                WriteToLogFile($"【异常】处理失败: {ex.Message}");
                // 异常情况下，重置流程状态以允许下一个扫码
                _isWaitingForResult = false;
                _currentProcessingBarcode = string.Empty;
            }
        }

        /// <summary>
        /// 触发 MES 接口查询并处理结果，更新 UI
        /// </summary>
        //     private async void TriggerMesQuery(string barcode)
        //     {
        //         // 准备 UI
        //         this.u9No_textBox.Text = "";
        //         this.partNo_textBox.Text = "";
        //         this.isFinish_textBox.Text = "";
        //         this.isFinish_textBox.BackColor = System.Drawing.Color.White;

        //         bool isCompleteStatus = false;
        //         string resultJson = string.Empty;

        //         try
        //         {
        //             // 1. 异步调用 MES 服务
        //             var mesResult = await _mesService.CheckPreviousProcessAndParseAsync(barcode);

        //             if (mesResult.Success)
        //             {
        //                 isCompleteStatus = mesResult.IsComplete;

        //                 // 填充 UI 字段
        //                 this.u9No_textBox.Text = mesResult.U9No;
        //                 this.partNo_textBox.Text = mesResult.Specs;

        //                 // 处理 isComplete 状态并设置颜色
        //                 string completeText = isCompleteStatus ? "是" : "否";
        //                 System.Drawing.Color completeColor = isCompleteStatus ? System.Drawing.Color.LightGreen : System.Drawing.Color.Red;

        //                 this.isFinish_textBox.Text = completeText;
        //                 this.isFinish_textBox.BackColor = completeColor;

        //                 // 记录日志 
        //                 string logResultMsg = isCompleteStatus
        //? $"前工序检查通过: 产品编码: {mesResult.Specs}"
        //: $"前工序检查未通过，原因: {mesResult.Reason}";
        //                 WriteToLogFile(logResultMsg);
        //             }
        //             else
        //             {
        //                 // MES 接口返回非成功状态
        //                 this.isFinish_textBox.Text = "接口异常";
        //                 this.isFinish_textBox.BackColor = System.Drawing.Color.Red;
        //                 this.u9No_textBox.Text = "";
        //                 this.partNo_textBox.Text = "";
        //                 WriteToLogFile($"MES 接口返回异常: {mesResult.Reason}");
        //             }
        //         }
        //         catch (Exception ex)
        //         {
        //             // 捕获所有处理异常 (网络, JSON解析, etc.)
        //             this.isFinish_textBox.Text = "调用/处理错误";
        //             this.isFinish_textBox.BackColor = System.Drawing.Color.Red;
        //             WriteToLogFile($"内部处理错误: {ex.Message}");
        //         }

        //         // 4. TCP 发送核心逻辑 (不论 MES 结果如何，都发送给 VisionMaster)
        //         string dataToSend = $"{barcode},{isCompleteStatus.ToString().ToLower()}";
        //         await Task.Run(() => _tcpClientManager.SendDataToTcpServer(dataToSend));
        //     }

        //private async void TriggerMesQuery(string barcode)
        //{
        //    // 准备 UI
        //    this.u9No_textBox.Text = "";
        //    this.partNo_textBox.Text = "";
        //    this.isFinish_textBox.Text = "";
        //    this.isFinish_textBox.BackColor = System.Drawing.Color.White;

        //    // UI 上的最终结果先清除
        //    Label statusControl = this.Controls.Find("statusTextLabel", true).FirstOrDefault() as Label;
        //    if (statusControl != null)
        //    {
        //        statusControl.Text = "..."; // 或 "检测中"
        //        statusControl.BackColor = Color.LightGray;
        //        statusControl.ForeColor = Color.Black;
        //    }


        //    bool isCompleteStatus = false; // 用于后续的 IsComplete 逻辑
        //    string dataToSendToVM = string.Empty; // 用于发送给 VisionMaster 的数据

        //    try
        //    {
        //        // 1. 异步调用 MES 服务
        //        var mesResult = await _mesService.CheckPreviousProcessAndParseAsync(barcode);

        //        // 2. 处理 MES 结果（成功或失败）
        //        if (mesResult.Success)
        //        {
        //            isCompleteStatus = mesResult.IsComplete; // 记录前工序状态

        //            // 填充 UI 字段
        //            this.u9No_textBox.Text = mesResult.U9No;
        //            this.partNo_textBox.Text = mesResult.Specs;

        //            // 处理 isComplete 状态并设置颜色
        //            string completeText = isCompleteStatus ? "是" : "否";
        //            System.Drawing.Color completeColor = isCompleteStatus ? System.Drawing.Color.LightGreen : System.Drawing.Color.Red;
        //            this.isFinish_textBox.Text = completeText;
        //            this.isFinish_textBox.BackColor = completeColor;

        //            // 记录日志 
        //            string logResultMsg = isCompleteStatus ? $"前工序检查通过: 产品编码: {mesResult.Specs}" : $"前工序检查未通过，原因: {mesResult.Reason}";
        //            WriteToLogFile(logResultMsg);

        //            // 3. **【核心修改】** 根据零件号对比决定发送内容
        //            string currentSpecs = mesResult.Specs;
        //            WriteToLogFile($"MES 成功返回零件号: [{currentSpecs}]。上次零件号: [{(_lastSpecs ?? "无")}]");

        //            if (string.IsNullOrEmpty(_lastSpecs) || !currentSpecs.Equals(_lastSpecs, StringComparison.OrdinalIgnoreCase))
        //            {
        //                // 零件号不同或首次
        //                dataToSendToVM = currentSpecs;
        //                _lastSpecs = currentSpecs; // 更新上次零件号
        //                WriteToLogFile($"零件号发生变化或首次查询，发送新零件号给 VisionMaster (9527): [{dataToSendToVM}]");
        //            }
        //            else
        //            {
        //                // 零件号相同
        //                dataToSendToVM = "sameSpecs";
        //                WriteToLogFile($"零件号与上次相同，发送标识给 VisionMaster (9527): [{dataToSendToVM}]");
        //            }
        //        }
        //        else
        //        {
        //            // MES 接口返回非成功状态
        //            this.isFinish_textBox.Text = "接口异常";
        //            this.isFinish_textBox.BackColor = System.Drawing.Color.Red;
        //            this.u9No_textBox.Text = "";
        //            this.partNo_textBox.Text = "";
        //            WriteToLogFile($"MES 接口返回异常: {mesResult.Reason}。**不发送零件号给 VisionMaster**。");
        //            // MES 失败，重置流程锁
        //            _isWaitingForResult = false;
        //            _currentProcessingBarcode = string.Empty;
        //            WriteToLogFile("MES 查询失败，流程状态重置。");
        //            return; // 结束方法，不进行 TCP 发送
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        // 捕获所有处理异常 (网络, JSON解析, etc.)
        //        this.isFinish_textBox.Text = "调用/处理错误";
        //        this.isFinish_textBox.BackColor = System.Drawing.Color.Red;
        //        WriteToLogFile($"内部处理错误: {ex.Message}。**不发送零件号给 VisionMaster**。");
        //        // 异常，重置流程锁
        //        _isWaitingForResult = false;
        //        _currentProcessingBarcode = string.Empty;
        //        WriteToLogFile("处理 MES 结果异常，流程状态重置。");
        //        return; // 结束方法，不进行 TCP 发送
        //    }

        //    // 4. TCP 发送核心逻辑 (仅在 MES 查询成功后执行)
        //    // 发送零件号或 "sameSpecs" 给 VisionMaster (9527)
        //    if (!string.IsNullOrEmpty(dataToSendToVM))
        //    {
        //        await Task.Run(() => _tcpClientManager.SendDataToTcpServer(dataToSendToVM));
        //    }
        //    else
        //    {
        //        WriteToLogFile("警告：未能确定发送给 VisionMaster 的零件号数据。");
        //    }

        //    // 注意：流程锁 (_isWaitingForResult) 的解除现在完全依赖于 ProcessFinalResult 方法
        //}

        private async void TriggerMesQuery(string barcode)
        {
            // 准备 UI
            this.u9No_textBox.Text = "";
            this.partNo_textBox.Text = "";
            this.isFinish_textBox.Text = "";
            this.isFinish_textBox.BackColor = System.Drawing.Color.White;

            // UI 上的最终结果先清除
            Label statusControl = this.Controls.Find("statusTextLabel", true).FirstOrDefault() as Label;
            if (statusControl != null)
            {
                statusControl.Text = "..."; // 或 "检测中"
                statusControl.BackColor = Color.LightGray;
                statusControl.ForeColor = Color.Black;
            }


            bool isCompleteStatus = false; // 用于后续的 IsComplete 逻辑
            string dataToSendToVM = string.Empty; // 用于发送给 VisionMaster 的数据
            string specsOrIdentifier = string.Empty; // 用于存储零件号或标识

            try
            {
                // 1. 异步调用 MES 服务
                var mesResult = await _mesService.CheckPreviousProcessAndParseAsync(barcode);

                // 2. 处理 MES 结果（成功或失败）
                if (mesResult.Success)
                {
                    isCompleteStatus = mesResult.IsComplete; // 记录前工序状态

                    // 填充 UI 字段
                    this.u9No_textBox.Text = mesResult.U9No;
                    this.partNo_textBox.Text = mesResult.Specs;

                    // 处理 isComplete 状态并设置颜色
                    string completeText = isCompleteStatus ? "是" : "否";
                    System.Drawing.Color completeColor = isCompleteStatus ? System.Drawing.Color.LightGreen : System.Drawing.Color.Red;
                    this.isFinish_textBox.Text = completeText;
                    this.isFinish_textBox.BackColor = completeColor;

                    // 记录日志 
                    string logResultMsg = isCompleteStatus ? $"前工序检查通过: 产品编码: {mesResult.Specs}" : $"前工序检查未通过，原因: {mesResult.Reason}";
                    WriteToLogFile(logResultMsg);

                    // 3. **【新核心逻辑】** 决定发送的零件号或标识部分
                    string currentSpecs = mesResult.Specs;
                    WriteToLogFile($"MES 成功返回零件号: [{currentSpecs}]。上次零件号: [{(_lastSpecs ?? "无")}]");

                    if (string.IsNullOrEmpty(_lastSpecs) || !currentSpecs.Equals(_lastSpecs, StringComparison.OrdinalIgnoreCase))
                    {
                        // 零件号不同或首次
                        specsOrIdentifier = currentSpecs; // 发送新零件号
                        _lastSpecs = currentSpecs; // 更新上次零件号
                        WriteToLogFile($"零件号发生变化或首次查询，发送新零件号 ({currentSpecs}) 作为组合的一部分。");
                    }
                    else
                    {
                        // 零件号相同
                        specsOrIdentifier = "sameSpecs"; // 发送标识
                        WriteToLogFile($"零件号与上次相同，发送标识 (sameSpecs) 作为组合的一部分。");
                    }

                    // 4. **【构造最终发送数据】** 组合：启动码,是否完成(小写),零件号/标识
                    // 将 bool 转换为小写的 true/false 字符串
                    string isCompleteStr = isCompleteStatus.ToString().ToLower();
                    dataToSendToVM = $"{barcode},{isCompleteStr},{specsOrIdentifier}";

                    WriteToLogFile($"准备发送给 VisionMaster (9527) 的数据: [{dataToSendToVM}]");
                }
                else
                {
                    // MES 接口返回非成功状态
                    this.isFinish_textBox.Text = "接口异常";
                    this.isFinish_textBox.BackColor = System.Drawing.Color.Red;
                    this.u9No_textBox.Text = "";
                    this.partNo_textBox.Text = "";
                    WriteToLogFile($"MES 接口返回异常: {mesResult.Reason}。**不进行 TCP 发送**。");
                    // MES 失败，重置流程锁
                    _isWaitingForResult = false;
                    _currentProcessingBarcode = string.Empty;
                    WriteToLogFile("MES 查询失败，流程状态重置。");
                    return; // 结束方法，不进行 TCP 发送
                }
            }
            catch (Exception ex)
            {
                // 捕获所有处理异常 (网络, JSON解析, etc.)
                this.isFinish_textBox.Text = "调用/处理错误";
                this.isFinish_textBox.BackColor = System.Drawing.Color.Red;
                WriteToLogFile($"内部处理错误: {ex.Message}。**不进行 TCP 发送**。");
                // 异常，重置流程锁
                _isWaitingForResult = false;
                _currentProcessingBarcode = string.Empty;
                WriteToLogFile("处理 MES 结果异常，流程状态重置。");
                return; // 结束方法，不进行 TCP 发送
            }

            // 5. TCP 发送核心逻辑 (仅在 MES 查询成功后执行)
            if (!string.IsNullOrEmpty(dataToSendToVM))
            {
                await Task.Run(() => _tcpClientManager.SendDataToTcpServer(dataToSendToVM));
            }
            else
            {
                WriteToLogFile("警告：未能确定发送给 VisionMaster 的组合数据。");
            }

            // 注意：流程锁 (_isWaitingForResult) 的解除现在完全依赖于 ProcessFinalResult 方法
        }



        // ==========================================================
        // 日志和工具方法
        // ==========================================================

        // 线程安全地写入日志 (包括 UI 和文件)
        public void WriteToLogFile(string msg)
        {
            string formattedMsg = msg;

            // 检查日志是否包含原始 JSON 标记，只对它进行格式化
            if (msg.StartsWith("MES 接口返回原始 JSON:"))
            {
                int jsonStartIndex = msg.IndexOf(":") + 1;
                if (jsonStartIndex < msg.Length)
                {
                    string rawJson = msg.Substring(jsonStartIndex).Trim();
                    string prettyJson = FormatJson(rawJson);
                    formattedMsg = msg.Substring(0, jsonStartIndex).Trim() + Environment.NewLine + prettyJson;
                }
            }

            AppendLogToUI(formattedMsg);

            // 使用 lock 关键字确保只有一个线程能进入文件写入操作
            lock (_logFileLock)
            {
                try
                {
                    string logDir = Path.Combine(@"D:\", "ShangWeiDemoLogs");
                    if (!Directory.Exists(logDir))
                    {
                        Directory.CreateDirectory(logDir);
                    }
                    string logFileName = DateTime.Now.ToString("yyyyMMdd") + "_ScanLog.txt";
                    string logPath = Path.Combine(logDir, logFileName);

                    string logLine = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - {formattedMsg}";

                    File.AppendAllText(logPath, logLine + Environment.NewLine);
                }
                catch (Exception)
                {
                    // 忽略文件写入失败
                }
            }
        }

        // 线程安全地将日志内容追加到 UI 文本框
        private void AppendLogToUI(string message)
        {
            // 确保在 UI 线程执行
            if (this.logOutput_textBox == null) return;
            if (this.logOutput_textBox.InvokeRequired)
            {
                this.BeginInvoke(new Action<string>(AppendLogToUI), message);
                return;
            }

            // --- 以下代码在 UI 主线程执行 ---
            string logLine = $"{DateTime.Now:HH:mm:ss.fff} - {message}{Environment.NewLine}";

            // 限制行数
            if (this.logOutput_textBox.Lines.Length > 1000)
            {
                List<string> lines = this.logOutput_textBox.Lines.ToList();
                lines.RemoveRange(0, 100);
                this.logOutput_textBox.Lines = lines.ToArray();
            }

            this.logOutput_textBox.AppendText(logLine);
        }

        // 关键修复：恢复被删除的 click 事件处理函数
        private void viewLogToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem menuItem = (ToolStripMenuItem)sender;

            // 假设您有一个名为 logGroupBox 的 GroupBox 包裹 logOutput_textBox
            if (this.Controls.Find("logGroupBox", true).FirstOrDefault() is GroupBox logGroupBox)
            {
                logGroupBox.Visible = menuItem.Checked;
            }
            // 使用 logGroupBox.Visible 的前提是 logGroupBox 在设计器中存在，如果不存在，使用 this.logOutput_textBox.Parent.Visible = menuItem.Checked;
        }

        /// <summary>
        /// 尝试对给定的 JSON 字符串进行格式化（Pretty Print）。
        /// </summary>
        private string FormatJson(string jsonString)
        {
            try
            {
                var parsedJson = JsonConvert.DeserializeObject(jsonString);
                return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
            }
            catch
            {
                return jsonString;
            }
        }


    }
}